// Linux 内核0.11
// main.c
sched_init(); // 调度程序初始化(加载了任务0 的tr, ldtr) （kernel/sched.c）
// 调度程序的初始化⼦程序。
void sched_init(void)
{
    ... set_intr_gate(0x20, &timer_interrupt);
    // 修改中断控制器屏蔽码，允许时钟中断。
    outb(inb_p(0x21) & ~0x01, 0x21);
    // 设置系统调⽤中断⻔。
    set_system_gate(0x80, &system_call);
    ...
}
// system_call.s
_timer_interrupt : 
    ...
; // do_timer(CPL)执⾏任务切换、计时等⼯作，在kernel/shched.c,305 ⾏实现。
    call _do_timer;         // 'do_timer(long CPL)' does everything from
// 调度⼊⼝
void do_timer(long cpl)
{
    ... schedule();
}
void schedule(void)
{
    ... switch_to(next); // 切换到任务号为next 的任务，并运⾏之。
}

// void trap_init(void)
// {
//     int i;
//     set_trap_gate(0, &divide_error); // 设置除操作出错的中断向量值。以下雷同。
//     set_trap_gate(1, &debug);
//     set_trap_gate(2, &nmi);
//     set_system_gate(3, &int3); /* int3-5 can be called from all */
//     set_system_gate(4, &overflow);
//     set_system_gate(5, &bounds);
//     set_trap_gate(6, &invalid_op);
//     set_trap_gate(7, &device_not_available);
//     set_trap_gate(8, &double_fault);
//     set_trap_gate(9, &coprocessor_segment_overrun);
//     set_trap_gate(10, &invalid_TSS);
//     set_trap_gate(11, &segment_not_present);
//     set_trap_gate(12, &stack_segment);
//     set_trap_gate(13, &general_protection);
//     set_trap_gate(14, &page_fault);
//     set_trap_gate(15, &reserved);
//     set_trap_gate(16, &coprocessor_error);
//     // 下⾯将int17-48 的陷阱⻔先均设置为reserved，以后每个硬件初始化时会重新设置⾃⼰的陷阱⻔。 for (i = 17; i < 48; i++)
//     set_trap_gate(i, &reserved);
//     set_trap_gate(45, &irq13);              // 设置协处理器的陷阱⻔。
//     outb_p(inb_p(0x21) & 0xfb, 0x21);       // 允许主8259A 芯⽚的IRQ2 中断请求。
//     outb(inb_p(0xA1) & 0xdf, 0xA1);         // 允许从8259A 芯⽚的IRQ13 中断请求。
//     set_trap_gate(39, &parallel_interrupt); // 设置并⾏⼝的陷阱⻔。
// }

// void rs_init(void)
// {
//     set_intr_gate(0x24, rs1_interrupt); // 设置串⾏⼝1 的中断⻔向量(硬件IRQ4 信号)。
//     set_intr_gate(0x23, rs2_interrupt); // 设置串⾏⼝2 的中断⻔向量(硬件IRQ3 信号)。
//     init(tty_table[1].read_q.data);     // 初始化串⾏⼝1(.data 是端⼝号)。
//     init(tty_table[2].read_q.data);     // 初始化串⾏⼝2。
//     outb(inb_p(0x21) & 0xE7, 0x21);     // 允许主8259A 芯⽚的IRQ3，IRQ4 中断信号请求。
// }

// #include <iostream>
// #include <unistd.h>
// #include <cstdio>
// #include <sys/types.h>
// #include <sys/wait.h>
// void PrintPending(sigset_t &pending)
// {
//     std::cout << "curr process[" << getpid() << "]pending: ";
//     for (int signo = 31; signo >= 1; signo--)
//     {
//         if (sigismember(&pending, signo))
//         {
//             std::cout << 1;
//         }
//         else
//         {
//             std::cout << 0;
//         }
//     }
//     std::cout<< "\n";
// }
// void handler(int signo)
// {
//     std::cout << signo << " 号信号被递达!!!" << std::endl;
//     std::cout << "-------------------------------" << std::endl;
//     sigset_t pending;
//     sigpending(&pending);
//     PrintPending(pending);
//     std::cout << "-------------------------------" << std::endl;
// }

// int main()
// {
//     // 0. 捕捉2号信号
//     signal(2, handler); // ⾃定义捕捉
//     // signal(2, SIG_IGN); // 忽略⼀个信号
//     //signal(2, SIG_DFL); // 信号的默认处理动作
//     //  1. 屏蔽2号信号
//     sigset_t block_set, old_set;
//     sigemptyset(&block_set);
//     sigemptyset(&old_set);
//     sigaddset(&block_set, SIGINT); // 我们有没有修改当前进⾏的内核block表呢？？？1 0
//     // 1.1 设置进⼊进程的Block表中
//     sigprocmask(SIG_BLOCK, &block_set, &old_set); // 真正的修改当前进⾏的内核block表，完成了对2号信号的屏蔽！
//     int cnt = 15;
//     while (true)
//     {
//         // 2. 获取当前进程的pending信号集
//         sigset_t pending;
//         sigpending(&pending);
//         // 3. 打印pending信号集
//         PrintPending(pending);
//         cnt--;
//         // 4. 解除对2号信号的屏蔽
//         if (cnt == 0)
//         {
//             std::cout << "解除对2号信号的屏蔽!!!" << std::endl;
//             sigprocmask(SIG_SETMASK, &old_set, &block_set);
//         }
//         sleep(1);
//     }
// }

// #include <stdio.h>
// #include <signal.h>
// #include <unistd.h>

// int main() {
//     sigset_t new_mask, old_mask;

//     // 初始化新信号集，只包含 SIGINT
//     sigemptyset(&new_mask);
//     sigaddset(&new_mask, SIGINT);

//     // 设置新的信号屏蔽字，阻塞 SIGINT 信号
//     if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) == -1) {
//         perror("sigprocmask");
//         return 1;
//     }

//     printf("SIGINT signal is blocked. Sleeping for 5 seconds...\n");
//     sleep(5);

//     // 解除对 SIGINT 的阻塞
//     if (sigprocmask(SIG_UNBLOCK, &new_mask, NULL) == -1) {
//         perror("sigprocmask");
//         return 1;
//     }

//     printf("SIGINT signal is unblocked.\n");

//     return 0;
// }

// struct task_struct
// {
//     ...
//         /* signal handlers */
//         struct sighand_struct *sighand;
//     sigset_t blocked struct sigpending pending;
//     ...
// }
// struct sighand_struct
// {
//     atomic_t count;
//     struct k_sigaction action[_NSIG]; // #define _NSIG 64
//     spinlock_t siglock;
// };
// struct __new_sigaction
// {
//     __sighandler_t sa_handler;
//     unsigned long sa_flags;
//     void (*sa_restorer)(void); /* Not used by Linux/SPARC */
//     __new_sigset_t sa_mask;
// };
// struct k_sigaction
// {
//     struct __new_sigaction sa;
//     void __user *ka_restorer;
// };
// /* Type of a signal handler. */
// typedef void (*__sighandler_t)(int);
// struct sigpending
// {
//     struct list_head list;
//     sigset_t signal;
// };